#include"../../inc/net/SocketIO.h"
#include<unistd.h>
#include<errno.h>
#include<sys/socket.h>

namespace SE
{
    SocketIO::SocketIO(int fd)
    : _fd(fd)
    {}

    int SocketIO::readn(char* buf, int len)
    {
        int ret, left = len;
        char* p = buf;
        while(left > 0)
        {
            ret = ::read(_fd, p, left);
            if(-1 == ret && errno == EINTR)
                continue;
            else if(-1 == ret)
            {
                logError("readn");
                return len - left;
            }
            else if(0 == ret)            
            {
                return len - left;
            }
            else 
            {
                left -= ret;
                p += ret;
            }
        }
        return len - left;
    }

    int SocketIO::readline(char* buf, int len)
    {
        int left = len-1;
        char* p = buf;
        int ret = 0;
        int total = 0;
        while(left > 0)
        {
            ret = recvPeek(p, left);
            for(int i = 0; i != ret; i++)
            {
                if(p[i] == '\n')
                {
                    readn(p, ++i);
                    total += i;
                    *(p + i) = '\0';
                    return total;
                }
            }
            // if not find \n
            readn(p, ret);
            left -= ret;
            p += ret;
            total += ret;
        }
        *p = '\0';
        return total;
    }

    int SocketIO::writen(const char* buf, int len)
    {
        int ret, left = len;
        const char* p = buf;
        while(left > 0)
        {
            ret = ::write(_fd, p, left);
            if(-1 == ret && errno == EINTR)
                continue;
            else if(-1 == ret)
            {
                logError("writen");
                return len - left;
            }
            else 
            {
                left -= ret;
                p += ret;
            }
        }
        return len - left;
    }

    int SocketIO::recvPeek(char* buf, int len)
    {
        int ret;
        do
        {
            ret = recv(_fd, buf, len, MSG_PEEK);
        }while (-1 == ret && errno == EINTR);
        return ret;
    }
}